home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#21 (Jun 87)
/
format source
/
SCSI.a
< prev
next >
Wrap
Text File
|
1987-05-07
|
25KB
|
810 lines
;*********************** File: SCSI.a *************************
;**************************************************************
;
; This file contains all the items in the SCSI menu. It also
; contains the SCSI primatives for comunication with SCSI hard
; disks.
;
; Note: All the symbols that are declared or imported before
; start of the first module (PROC, MAIN or RECORD) are defined
; for all modules in this file. Forward references to other
; modules in a file must be imported.
INCLUDE 'FormatEqu.a'
LOAD 'Traps.d'
LOAD 'ToolEqu.d'
LOAD 'SysEqu.d'
LOAD 'QuickEqu.d'
LOAD 'SCSIEqu.d'
EXPORT (Res,Last_Cmd,CompStat,CompMsg):DATA
EXPORT (BadB_Num):DATA
Addr ds.w 1 ;address of hard disk
Heads ds.l 1 ;number of heads on hard disk
Cyls ds.l 1 ;number of cylinders on hard disk
WrtPreComp ds.l 1 ;cylinder to start write precompensation
RedWrtCur ds.l 1 ;cylinder to start reduced write current
Interleave ds.w 1 ;interleave number to be used
StepCode ds.w 1 ;type of step pulse used
CompStat ds.w 1 ;status from _SCSIComplete
CompMsg ds.w 1 ;message from _SCSIComplete
Res ds.w 1 ;result from SCSI commands
Last_Cmd ds.w 1 ;last command executed
BadB_Num ds.l 1 ;total number of bad blocks
IMPORT (DialogPort,ItemType,ItemHandle,ItemRect):DATA
IMPORT (EventLoop,DefButton,RadioHiLite):CODE
IMPORT (CountOff,ExtractNumb,SortBuff,OutBuff):CODE
IMPORT (ErrorProc,ClearBuff):CODE
IMPORT (DialogBuff,ButtonHit):DATA
IMPORT (StrBuff1,StrBuff2,StrBuff3,StrBuff4):DATA
Buffers RECORD EXPORT
EXPORT (CommandBuff,PseudoProg,ParamBuff):DATA
EXPORT (BadB_List,BadB_Out):DATA
ALIGN 2
CommandBuff ds.b CBuffLen ;buffer for SCSI commands
PseudoProg ds.b PProgLen ;buffer for pseudo program
ParamBuff ds.b ParamBuffLen ;buffer for parameters
BadB_List ds.l MaxBBListLen ;buffer area for entering and
;sorting bad blocks
BadB_Out ds.l MaxBBOutLen ;buffer area for output to
;to the disk drive
ENDR
; PROC SelAddrProc
;
; This procedure gets the address of the device to be formatted
; from the user. It then tests to see if the device is connected
; and if the device is ready to be formatted. If either of these
; are false, it jumps to ErrorProc (error handling procedure).
SelAddrProc PROC EXPORT
IMPORT (Hd_Select,HD_TestUnit,HD_Discon):CODE
IMPORT (UnHiLite,ResetDisk):CODE
clr.l -(A7) ;space for pointer to dialog
move.w #SelAddrRN,-(A7) ;select address dialog resource#
pea DialogBuff(A5) ;push pointer to dialog storage
move.l #-1,-(A7) ;make dialog top most window
_GetNewDialog
move.l (A7),DialogPort(A5) ;save pointer to dialog and
;leave a copy on the stack the
;for call to _SetPort
_SetPort
lea DialogBuff(A5),A4 ;pass address of dialog record
jsr DefButton ;make default = "Select" button
move.w #10,D0 ;make Mac's address grey
jsr UnHiLite
; Register ussage:
; D0 Radio button that was selected, now must be unselected
; D1 Radio button that was just clicked on; to be selected
; Initialize D0 and D3 for first call to RadioHiLite. D0=0
; is flag for no radio button to deselect. D1=3 is to set the
; default SCSI address = 0.
clr.l D0
moveq.l #3,D7
NotYet
move.w D7,D1 ;update D1 (pass to RadioHiLite)
jsr RadioHiLite ;change radio button selected
clr.l -(A7) ;use standard filter proc function
pea ButtonHit(A5)
_ModalDialog
cmpi.w #2,ButtonHit(A5) ;was select or cancel button hit
ble EndDialog ;yes, so close up dialog
move.l D7,D0 ;D0 = id of old radio button
move.w ButtonHit(A5),D7 ;D7 = id of new radio button
bra.s NotYet ;loop back for next mouse down
EndDialog
move.l DialogPort(A5),-(A7) ;pass address of Dialog Rec
_CloseDialog ;close dialog
cmpi.w #2,ButtonHit(A5) ;was ok button hit
blt Continue ;yes
jmp EventLoop ;no, go get next event
Continue
subq.w #3,D7 ;D7 = last radio button hit, so
;subtract item # for radio
;button "0"
move.w D7,Addr(A5) ;D7 now equals address selected
jsr ResetDisk ;reset SCSI bus
tst.w Res(A5) ;did we succeed
bne ToErrorProc ;no, go handle error
; This next block of code, though the end of this procedure, is
; an example of how all SCSI commands are done. You can replace
; the SCSI command Test Unit Ready with any other SCSI command.
; The Mode Select and Format Unit commands used in FormatProc
; differ only in that data is transfered after the command.
; First we get control of the bus and select the target device.
jsr HD_Select ;go get control of bus and
;select device
tst.w Res(A5) ;did we succeed
bne ToErrorProc ;no, go handle error
; Second, we clear the buffer we use to construct the SCSI
; command in.
lea CommandBuff(A5),A0 ;pass address of buffer in A0
move.l #CBuffLen,D0 ;pass buffer size in D0
jsr ClearBuff ;clear buffer
; Third, we construct the command. This one has no parameters
; in the CDB (Command Desciption Block), so we only have to move
; the SCSI OP code into the CDB.
move.b #TestUReady,CommandBuff(A5) ;move OP code into byte
;1 of the CDB
clr.w -(A7) ;clear space for trap result
pea CommandBuff(A5) ;pass address of CDB
move.w #CommLenS,-(A7) ;pass length of command. This is
;a class 0 SCSI command, so
;the length is 6 bytes.
; Fourth, we send the command and test if it succeded.
_SCSICmd ;send command to target
move.w #TestUReady,Last_Cmd(A5) ;store command id
move.w (A7)+,Res(A5) ;test result, was there an error
bne ToErrorProc ;yes go to error proc
; Then, we wait for the target device send the Status and
; Message bytes. The target device will then release the Mac.
move.l #10,D0 ;pass number of ticks to wait
jsr HD_Discon ;proc that handles _SCSIComplete
tst.w Res(A5) ;SCSI Protocal Error?
bne ToErrorProc ;yes, go handle display error
; Lastly, we test the Status byte returned by _SCSIComplete.
; This is the SCSI command result code. It will tell us about
; the drives condition and if it is ready to be formated.
move.w #TestUReady,Last_Cmd(A5) ;store command id for
;error handling proc
cmp.w #3,CompStat(A5) ;is there a Write Fault?
beq ToErrorProc ;yes, go to error handling proc
cmp.w #4,CompStat(A5) ;is the Drive Not Ready?
beq ToErrorProc ;yes, go to error handling proc
cmp.w #20,CompStat(A5) ;is this SCSI command supported?
beq ToErrorProc ;no, go to error handling proc
jmp EventLoop
ToErrorProc
jmp ErrorProc
EndProc
; PROC ParamProc
;
; We give the user is given dialog box to input parameters used
; for formatting drive. We then extract the values from the
; TextEdit fields and place the hex values in the appropiate
; global variables. All values are checked against maximum
; values to make sure they are reasonable.
ParamProc PROC EXPORT
clr.l -(A7) ;space for pointer to dialog
move.w #ParamRN,-(A7) ;parameter dialog resource numb.
pea DialogBuff(A5) ;push pointer to dialog storage
move.l #-1,-(A7) ;dialog on top of all windows
_GetNewDialog
move.l (A7),DialogPort(A5) ;save pointer to dialog and
;leave copy on stack for
;call to _SetPort
_SetPort
lea DialogBuff(A5),A4 ;pass address of dialog record
jsr DefButton ;make "OK" button the default
; Now we set up our dialog box. First two calls to RadioHiLite
; have D0=0 as a flag for no radio button to unselect
; Register ussage:
; D0 Radio button that was selected, now must be unselected
; D1 Radio button that was just clicked on; to be selected
; D6 Interleave Radio Button that is currently selected
; D7 Step Rate Radio Button that is currently selected
moveq.l #3,D6 ;default interleave = 1:1
moveq.l #7,D7 ;default step pulse = 3 msec
; High light default interleave and step pulse radio buttons.
move.w D6,D1
clr.w D0
jsr RadioHiLite
clr.w D0
move.w D7,D1
jsr RadioHiLite
NotYet
clr.l -(A7) ;use standard filter proc function
pea ButtonHit(A5) ;push address of storage for item#
_ModalDialog
move.w ButtonHit(A5),D1 ;move item number to D1
cmpi.w #2,D1 ;was OK or Cancel selected?
ble EndDialog ;yes, go close up dialog
cmpi.w #9,D1 ;was text edit item hit
bgt NotYet ;yes, loop back for next event
cmpi.w #6,D1 ;was interleave radio button hit
bgt StepRate ;no, must be step rate radio button
; Interleave radio button was selected. Update D6 and select
; the correct radio button.
move.w D6,D0
move.w D1,D6
jsr RadioHiLite
bra.s NotYet
; Step rate radio button was selected. Update D7 and select
; the correct radio button.
StepRate:
move.w D7,D0
move.w D1,D7
jsr RadioHiLite
bra NotYet
EndDialog
cmpi.w #2,ButtonHit(A5) ;was "Cancel" selected?
blt Continue ;no
bra exit ;yes, so exit
; "OK" button selected so we can update the global variables
; that contain the step code and the interleave values.
Continue
subq.w #2,D6
move.w D6,Interleave(A5)
subq.w #7,D7
move.w D7,StepCode(A5)
; For each of the TextEdit fields we place the address of the
; global variable in A3, the item # in D0 and the maximum value
; in D3. We then call ExtractNumb to get the hex, insure that
; it is not over the maximum value, and place the hex number in
; the global variable.
lea Heads(A5),A3 ;extract number of heads from
move.l #10,D0 ;item number 10
move.l #MaxHeads,D3
jsr ExtractNumb
lea Cyls(A5),A3 ;extract number of cylinders
move.l #11,D0 ;from item number 11
move.l #MaxCylind,D3
jsr ExtractNumb
lea RedWrtCur(A5),A3 ;extract reduced write current
move.l #12,D0 ;cylinder from item #12
move.l Cyls(A5),D3
jsr ExtractNumb
lea WrtPreComp(A5),A3 ;extract write precompensation
move.l #13,D0 ;cylinder from item #13
move.l Cyls(A5),D3
jsr ExtractNumb
Exit
move.l DialogPort(A5),-(A7) ;pass pointer to Dialog rec
_CloseDialog ;close dialog box
jmp EventLoop ;return to event loop
EndProc
; PROC EDefectProc
;
; Here we ask the user to enter the defects that are listed on
; the sheet that came with their disk drive. They can enter as
; many as 60 defects. Since our dialog box only has room for 12
; defects, we ask the user to hit the "More" button if they have
; additional defects. We give the user a dialog box when they
; cannot enter any more defects.
;
; Register Ussage:
; D0 Index for next item in dialog that is EditText that
; we are going to remove a value from
; D6 Index for record being input in defect list; index
; is byte index of first field in record, not
; actual record number
EDefectProc PROC EXPORT
clr.l BadB_Num(A5) ;clear global for # of defects
; Clear our defect buffer.
move.l #MaxBBListLen,D0 ;pass buffer size in D0
lea BadB_List(A5),A0 ;pass address in A0
jsr ClearBuff ;go clear buffer
LoopForMore
clr.l D6 ;clear buffer record index
clr.l -(A7) ;space for pointer to dialog rec
move.w #EDefectsRN,-(A7) ;Enter Defects Dialog resource #
pea DialogBuff(A5) ;pass pointer to dialog storage
move.l #-1,-(A7) ;make this window on top
_GetNewDialog ;get dialog
move.l (A7),DialogPort(A5) ;save pointer to dialog and
;leave a copy on stack for
;call to _SetPort
_SetPort
lea DialogBuff(A5),A4 ;pass address of dialog record
jsr DefButton ;outline default button
NotYet
clr.l -(A7) ;use standard filter proc function
pea ButtonHit(A5) ;place for button hit
_ModalDialog ;handle dialog events
cmpi.w #3,ButtonHit(A5) ;is "Cancel" button hit?
blt EndDialog ;no, "More" or "OK" buttons were hit
bgt NotYet ;no, not a button, get another event
; User hit "Cancel" button, so clear defect count and return
; go close dialog box
clr.l BadB_Num(A5)
bra exit
; We want to close up the dialog, but first we must extract the
; defect data that the user has entered.
EndDialog
move.l BadB_Num(A5),D6 ;move number of defects into D6
lsl.l #4,D6 ;multiply by 16 to get byte
;index for first field in
;next empty record
lea BadB_List(A5),A0 ;A0 points 1st byte of buffer
AddToBuff
move.l #3,D0 ;first item is 4, so put 3 in D0
LoopAddBuff
; First we extract the cylinder number. We use the ExtractNumb
; procedure which takes the address for the result in A3, the
; maximum value in D3 and the item number in D0.
addq.l #1,D0 ;increment D0 by 1, next item
lea CylBBuff(A0,D6.L),A3
move.l #MaxCylind,D3
jsr ExtractNumb
; Next we extract the head number
addq.l #1,D0
lea HeadBBuff(A0,D6.L),A3
move.l #MaxHeads,D3
jsr ExtractNumb
; Lastly we extract the Bytes From Index value.
addq.l #1,D0
lea BFIBBuff(A0,D6.L),A3
move.l #MaxBFI,D3
jsr ExtractNumb
; Test to see if the cylinder number was 0. If so ignore this
; record as it was either empty or invalid. Most controller
; cards cannot take defects in track 0.
tst.l CylBBuff(A0,D6.L) ;is cylinder value valid
bne IncrCounters ;yes increment counters
; Otherwise, don't increment counters and next record will
; overwrite this one which was invalid.
cmpi.l #39,D0 ;have we reached the last item
beq Exit ;yes, go close dialog box
bra LoopAddBuff ;no, go extract next record
; Cylinder number is not equal to 0 so this is a valid defect.
IncrCounters
cmpi.l #(MaxBBs-1)*BadBRecLen,D6 ;is our buffer full
beq.s Exit ;yes, so exit
add.l #BadBRecLen,D6 ;increment buffer index
cmpi.l #39,D0
bne LoopAddBuff
Exit
lsr.l #4,D6 ;byte count/16 = number of defects
move.l D6,BadB_Num(A5) ;store defect number in global
move.l DialogPort(A5),-(A7) ;pass pointer to dialog
_CloseDialog ;close up dialog
cmpi.l #60,BadB_Num(A5) ;are there too many bad blocks
beq.s NoMoreAlert ;yes, go put up alert
cmpi.l #2,D5 ;did user hit "More" button (#2)
bne ToEventLoop ;no, so go to event loop
bra LoopForMore ;yes so put up dialog again
ToEventLoop
jmp EventLoop
NoMoreAlert
move.w #134,-(A7) ;get our out of buffer space alert
clr.l -(A7) ;use standard filter proc function
_CautionAlert ;use a caution alert
jmp EventLoop
EndProc
; PROC FormatProc
;
; Formating procedure. This is where we sent the drive
; parameters in a Mode Select command. We then send the drive
; defects with the Format Unit command. And then the drive is
; ready to use with a driver installing program.
FormatProc PROC EXPORT
IMPORT (HD_Select,HD_Discon,WriteDisk):CODE
; First we put up a dialog box to make sure the user wants to
; format the drive.
; Make String buffer #1, 1 character long. Then move the hex
; value in the low order byte of Addr (the SCSI address of the
; target device) into the string buffer and convert it to ascii.
move.b #1,StrBuff1(A5)
move.b 1+Addr(A5),1+StrBuff1(A5)
add.b #$30,1+StrBuff1(A5)
clr.b StrBuff2(A5) ;clear all the other string buffers
clr.b StrBuff3(A5)
clr.b StrBuff4(A5)
pea StrBuff1(A5)
pea StrBuff2(A5)
pea StrBuff3(A5)
pea StrBuff4(A5)
_ParamText ;substitute String buffer 1 for "^0"
move.w #132,-(A7) ;get format alert dialog box
clr.l -(A7) ;use standard filter proc function
_CautionAlert
cmpi.w #1,(A7)+ ;did user hit cancel?
bne Exit ;yes, so exit
; User wants to Zap Drive, so let 'em have it! First we
; construct a data block to place parameters that we will send
; with the Mode Select command.
ZapDrive
; First we clear the data buffer
lea ParamBuff(A5),A0 ;pass address of buffer
move.l #ParamBuffLen,D0 ;pass length of buffer
jsr ClearBuff ;clear buffer
clr.l D0 ;clear D0, used for scratch
; Header:
move.b #8,$3(A0) ;3rd byte = size of descriptor
;list
; Descriptor List:
move.b #2,$A(A0) ;high byte of sector size ($200)
; Drive Parameter List:
move.b #1,$C(A0) ;List Format Code: (1 = soft
;sectored drives, 2= hard
;sectored drives or
;removable media drives)
; Place word value of cylinder count into buffer. We must do
; this as two bytes because the wored in the output buffer is
; at an odd address
move.w 2+Cyls(A5),D0
move.b D0,$E(A0) ;make sure $E(A0) has LSB
lsr.l #8,D0 ;now move in high byte of word
move.b D0,$D(A0)
; Move byte value of head count into buffer.
move.b 3+Heads(A5),$F(A0)
; Move word value of Reduced Write Current Cylinder into buffer.
move.w 2+RedWrtCur(A5),$10(A0)
; Move word value of Write Precompensation Cylinder into buffer.
move.w 2+WrtPreComp(A5),$12(A0)
; Move byte value of Step Pulse Code into Buffer.
move.b 1+stepcode(A5),$15(A0)
; Now we send the Mode Select Command and the parameter buffer.
jsr HD_Select ;get SCSI bus and select drive
tst.w Res(A5) ;did we succeed?
bne ToErrorProc ;no, so go to error handling proc
; Clear command buffer and construct command.
lea CommandBuff(A5),A0 ;pass address of buffer
move.l #CBuffLen,D0 ;pass length of buffer
jsr ClearBuff ;clear command buffer
move.b #ModeSelect,(A0) ;move SCSI OP Code into byte #0
move.b #ModeSelBytesOut,4(A0) ;move # of bytes to transfer
;into byte #4
clr.w -(A7) ;space for trap error code
move.l A0,-(A7) ;pass address of command buffer
move.w #CommLenS,-(A7) ;pass length of CDB (Command Data
;Block), class 0 command, so it
;is 6 bytes long
_SCSICmd ;send command
move.w #ModeSelect,Last_Cmd(A5) ;store command id
move.w (A7)+,Res(A5) ;did command work?
bne ToErrorProc ;no, go to error handling proc
; Now we clear the pseudo program buffer and call the procedure
; WriteDisk to send the data to the controller card.
lea PseudoProg(A5),A0 ;pass address of buffer
move.l #PProgLen,D0 ;pass size of buffer
jsr ClearBuff ;clear buffer
lea ParamBuff(A5),A1 ;pass address of data buffer
move.l #ModeSelBytesOut,D0 ;pass # of bytes to transfer
jsr WriteDisk ;send data
move.l #10,D0 ;pass number of ticks to wait
jsr HD_Discon
tst.w Res(A5) ;SCSI Protocal Error?
bne ToErrorProc
move.w #ModeSelect,Last_Cmd(A5)
cmp.w #$4,CompStat(A5) ;is the Drive Not Ready?
beq ToErrorProc ;yes, go to error handling proc
cmp.w #$24,CompStat(A5) ;Was a bad parameter passed to
;the controller?
beq ToErrorProc ;yes, go to error handling proc
jsr HD_Select ;go get control of bus and
;select device
tst.w Res(A5) ;did we succeed
bne ToErrorProc ;no, go to error proc
; Next, clear the buffer where we will assemble the CDB (Command
; Data Block).
lea CommandBuff(A5),A0 ;pass address of buffer
move.l #CBuffLen,D0 ;pass size of buffer
jsr ClearBuff ;clear buffer
move.b #FormatUnit,(A0) ;move op code into first byte
move.b 1+Interleave(A5),4(A0) ;move byte value of inter
;leave into byte 4
tst.l BadB_num(A5) ;see if there are disk defects
beq NoDefects ;no, skip ahead
add.b #$1C,1(A0) ;place flags to tell controller
;that defects are coming
; Call OutBuff to format defects so they can be read by
; controller card.
jsr OutBuff
NoDefects
clr.w -(A7) ;space for trap error code
move.l A0,-(A7) ;pass address of CDB
move.w #CommLenS,-(A7) ;class 0 command so pass length
;of 6 bytes
_SCSICmd ;send command
move.w #FormatUnit,Last_Cmd(A5) ;store command id
move.w (A7)+,Res(A5) ;did _SCSICmd produce an error
bne ToErrorProc ;yes, go to error handling proc
; If we are sending any info on disk defects, prepare buffer for
; pseudo program and pass count bytes and address to sending
; procedure.
tst.l BadB_num(A5) ;are we sending any defect data?
beq NoPseudoProg ;no, skip the next section
; Clear pseudo program buffer.
lea PseudoProg(A5),A0 ;pass address of buffer
move.l #PProgLen,D0 ;pass length of buffer
jsr ClearBuff ;clear buffer
; Pass address of data, and number of bytes to be transfered. A0
; still contains the address of the pseudo program buffer.
lea BadB_Out(A5),A1
move.l BadB_Num(A5),D0 ;move number of defects to D0
lsl.l #3,D0 ;multiply by 8 (8 bytes/defect)
addq.l #4,D0 ;add 4 bytes for header
jsr WriteDisk ;send info on defects
NoPseudoProg
move.l #MaxTicks,D0 ;pass number of ticks to wait
jsr HD_Discon
tst.w Res(A5) ;SCSI Protocal Error?
bne ToErrorProc ;yes, go to error handling proc
; Test Status byte from SCSI command to see if we passed a bad
; parameter or if there is a defect on track 0.
move.w #FormatUnit,Last_Cmd(A5) ;update command id for
;error handling proc
cmp.w #$24,CompStat(A5) ;Was a bad parameter passed to
;the controller?
beq ToErrorProc ;yes, go to error proc
jmp EventLoop
Exit
jmp EventLoop
ToErrorProc
jmp ErrorProc
EndProc
; PROC ResetProc
;
; This procedure is called from the menu handling routine. It
; acts as glue between the menu handling code and the reset
; subroutine and allows us to use the reset subroutine elsewhere
; (like in SelAddrProc).
ResetProc PROC EXPORT
IMPORT (ResetDisk):CODE
jsr ResetDisk ;go reset SCSI bus
tst.w Res(A5) ;test result
bne ToErrorProc ;if error go to error handling proc
jmp EventLoop ;else return to event loop
ToErrorProc
jmp ErrorProc
EndProc
; PROC WriteDisk
;
; Procedure wor transfering data to the controller. This
; routine uses a pseudo program which contains a simple loop of
; three instructions. This transfer could have been accomplished
; using only the first and the last instruction if we had put
; the transfer count that is passed in D0 into the second
; parameter of the first command. It would look exactly the
; same if it were being used for a read, except the _SCSIWrite
; trap would be replaced with _SCSIRead. Refer to IM volume IV
; for info on the Pseudo instructions. Note each instruction is
; a word followed by two longword parameters. SCSTOP must be
; the last instruction. Address of pseudo buffer is passed in
; A0. Address of p_buff is passed in A1. Transfer count is
; passed in D0.
WriteDisk PROC ENTRY
movem.l D0-D2/A0-A1,-(SP) ;save registers
; First command moves bytes to given address
move.w #SCINC,(A0)
move.l A1,2(A0) ;address to be moved to or from
move.l #1,6(A0) ;transfer count in bytes
; Second command is loop
move.w #SCLOOP,10(A0)
move.l #-10,12(A0) ;rel addr
move.l d0,16(A0) ;loop count
; Third command = stop, no parameters
move.w #SCSTOP,20(A0)
clr.w -(SP) ;space for trap result code (OSErr)
move.l A0,-(SP) ;address of pseudo program
_SCSIWrite
move.w (SP)+,Res(A5) ;store result
move.w #Write,Last_Cmd(A5) ;store code for type of SCSI
;command
movem.l (SP)+,D0-D2/A0-A1 ;restore registers
rts
ENDPROC
; PROC HD_Select
;
; HD_Select tries to get control of the SCSI bus. If it does,
; it then selects the device whose address is in Addr(A5).
HD_Select PROC ENTRY
IMPORT CountOff:CODE
movem.l D0-D2/A0-A1,-(A7) ;save regs on stack
clr.w -(A7) ;space for result code
_SCSIGet ;reserve the bus for our use
move.w (A7)+,Res(A5) ;store result code
beq.s ok ;go to ok2 if we succeeded
move.w #Get,Last_Cmd(A5) ;else, store the last command
bra.s exit ;and return
ok
clr.w -(A7) ;space for result code
move.w Addr(A5),-(A7) ;load SCSI address of hard disk
_SCSISelect ;select device
move.w (A7)+,Res(A5) ;store result code
move.w #Select,Last_Cmd(A5) ;store last command
exit
movem.l (A7)+,D0-D2/A0-A1 ;restore registers
rts
ENDPROC
; PROC HD_Discon
;
; Here we complete a SCSI command. We tell the Mac how long to
; wait for the target device on the SCSI bus to signal that the
; command has completed. This procedure receives the number of
; ticks to wait in D0.
HD_Discon PROC ENTRY
movem.l D0-D2/A0-A1,-(A7) ;save regs on stack
clr.w CompStat(A5)
clr.w CompMsg(A5)
clr.w -(A7) ;space for result code
pea CompStat(A5) ;_SCSIComplete Status
pea CompMsg(A5) ;_SCSIComplete Message
move.l D0,-(A7) ;number of ticks to wait for
;completion of the last
;SCSI command
_SCSIComplete
move.w (A7)+,Res(A5) ;store result code
move.w #Complete,Last_Cmd(A5) ;store last command
movem.l (A7)+,D0-D2/A0-A1 ;restore registers
rts
ENDPROC
; PROC InitGlobals
;
; Initialize the globals used to store information about the
; hard disk. Set all values to zero
InitGlobals PROC EXPORT
clr.w Heads(A5)
clr.w Cyls(A5)
clr.w WrtPreComp(A5)
clr.w RedWrtCur(A5)
clr.w Interleave(A5)
clr.w StepCode(A5)
clr.l Addr(A5)
clr.l BadB_Num(A5)
rts
ENDPROC
; PROC ResetDisk
;
; This procedure resets the SCSI bus. It has a one second delay
; after the reset because the CDC Wren III drives take more than
; 3/4 of a second to completely reset. Other drives may need
; longer delays after the reset.
ResetDisk PROC EXPORT
movem.l D0-D2/A0-A1,-(A7) ;save the registers
clr.w -(A7) ;space for result code
_SCSIReset ;reset the bus
move.w (A7)+,Res(A5) ;store results
beq.s ok1 ;go to ok1 if we succeeded
move.w #Reset,Last_Cmd(A5) ;else command code for error Msg
rts
ok1
move.l #60,D0 ;D0 = number of ticks to wait
jsr CountOff ;jst to delay routine
movem.l (A7)+,D0-D2/A0-A1 ;restore the registers
rts
ENDPROC
END